﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataPreparation;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace TMSimulator
{
    public static class Controller
    {
        public static GradedDB db = new GradedDB();// static field for form use
        public static List<FileAccess> monitorAccess = new List<FileAccess>();
        private static List<IFactor> _factors;
        private static IDistance _distance;
        private static string _logPath;
        private static bool writeMonitorToLog;

        public static bool WriteMonitorToLog
        {
            get { return Controller.writeMonitorToLog; }
            set { Controller.writeMonitorToLog = value; }
        }

        public static void DBinit()
        {
        }

        /// <summary>
        /// init system with the path of the log file,the method-fingerprints or cosine, and list of factors
        /// </summary>
        /// <param name="path"></param>
        /// <param name="method"></param>
        /// <param name="factors"></param>
        public static void InitializeSystem(string path, string method, List<IFactor> factors, string DBpath)
        {
            WriteMonitorToLog = false;
            //deserializable
            FileStream fs = new FileStream(DBpath, FileMode.Open);
            BinaryFormatter formatter = new BinaryFormatter();
            db = (GradedDB)formatter.Deserialize(fs);
            fs.Close();

            _factors = factors;

            if (method == "fingerprints")
            {
                _distance = new FingerprintDistance();
            }
            else
            {
                _distance = new CosineSimilarity();
            }

            UserManager.UserIndex.Clear();
            HandleFileAccess(FileAccessLogReader.getFileAccess(@path));
            _logPath = path;
        }

        public static void HandleFileAccess(List<FileAccess> fileAccess)
        {
            foreach (FileAccess acc in fileAccess)
            {
                HandleSingleFileAccess(acc);
            }
        }

        public static void HandleSingleFileAccess(FileAccess access)
        {
            double tmscore;
            User user;
            if (!UserManager.exists(access.Username))
            {
                user = new User(access.Username, access);
                UserManager.addUser(user);
                tmscore = _distance.getTMScore(access.FilePath, user, db);
                foreach (IFactor factor in _factors)
                {
                    tmscore = factor.getFactoredTMScore(tmscore, access.ExposureDuration);
                }
            }
            else
            {
                user = UserManager.getUser(access.Username);
                tmscore = _distance.getTMScore(access.FilePath, user, db);
                foreach (IFactor factor in _factors)
                {
                    if (factor.GetType() == typeof(ExposureTimeFactor))
                    {
                        tmscore = factor.getFactoredTMScore(tmscore - user.History.Values.Last(), access.ExposureDuration) + user.History.Values.Last();
                    }
                }
            }
            if (user != null)
            {
                user.History.Add(access, tmscore);
            }
            if (WriteMonitorToLog)
            {
                try
                {
                    using (StreamWriter w = File.AppendText(_logPath))
                    {
                        w.WriteLine(access.ToString());
                    }
                }
                catch (Exception e)
                {
                   
                }
            }

        }

        static void createSmallLog(string path)
        {
            StreamWriter writer = new StreamWriter(path, false);

            List<FileAccess> access = new List<FileAccess>();

            DateTime date;
            string username, file, author;
            TimeSpan span;
            double exposure;

            date = DateTime.Now;
            username = "bob";
            file = "44.txt";
            author = "author1";
            span = new TimeSpan(0, 20, 20);
            exposure = 0.35;
            access.Add(new FileAccess(date, username, file, author, span, exposure));

            date = DateTime.Now.AddMinutes(5);
            username = "bob";
            file = "46.txt";
            author = "author1";
            span = new TimeSpan(0, 0, 20);
            exposure = 0.05;
            access.Add(new FileAccess(date, username, file, author, span, exposure));

            date = DateTime.Now.AddMinutes(15);
            username = "bob";
            file = "47.txt";
            author = "author2";
            span = new TimeSpan(0, 1, 5);
            exposure = 1;
            access.Add(new FileAccess(date, username, file, author, span, exposure));

            date = DateTime.Now.AddMinutes(30);
            username = "alice";
            file = "60.txt";
            author = "author1";
            span = new TimeSpan(0, 5, 30);
            exposure = 0.95;
            access.Add(new FileAccess(date, username, file, author, span, exposure));

            date = DateTime.Now;
            username = "alice";
            file = "55.txt";
            author = "author2";
            span = new TimeSpan(0, 0, 5);
            exposure = 1;
            access.Add(new FileAccess(date, username, file, author, span, exposure));

            date = DateTime.Now.AddMinutes(40);
            username = "bob";
            file = "53.txt";
            author = "author2";
            span = new TimeSpan(0, 1, 5);
            exposure = 1;
            access.Add(new FileAccess(date, username, file, author, span, exposure));

            date = DateTime.Now.AddMinutes(50);
            username = "bob";
            file = "52.txt";
            author = "author2";
            span = new TimeSpan(0, 1, 5);
            exposure = 1;
            access.Add(new FileAccess(date, username, file, author, span, exposure));

            foreach (FileAccess fa in access)
            {
                writer.WriteLine(fa.Time + "," + fa.Username + "," + fa.FilePath + "," + fa.FileAuthor + "," + fa.ExposureDuration + "," + fa.FileExposurePercent);
            }
            writer.Close();
        }
    }
}

